package com.fram.common.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Random;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.DocumentHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.fram.common.canstant.PublicConstant;
import com.fram.common.util.date.DateUtils;
import com.fram.common.util.encryption.Base64;
import com.fram.common.util.encryption.MD5;

/*
 *@作者： 邪影
 *@时间： 2017年4月28日 - 下午1:24:21
 *@description：-> 公共方法
 */
public class PublicMethod {

	private static Logger LOG = LoggerFactory.getLogger(PublicMethod.class);

	/**
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:44:45 @版本：V1.0 @description：-> request
	 */
	public static HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:44:51 @版本：V1.0 @description：->response
	 */
	public static HttpServletResponse getResponse() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
	}

	public static String getUUIDUpperCase() {
		return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:45:02 @版本：V1.0 @description：-> 获取项目根目录
	 */
	public static String getProjectRootFile() {
		String ROOT_FILE = PublicMethod.class.getResource("").getPath().substring(1);
		ROOT_FILE = ROOT_FILE.substring(0, ROOT_FILE.indexOf("classes") + 7);
		return ROOT_FILE;
	}

	/** 得到上传缓存路径 **/
	public static String getCachePath() {
		String path = "";
		// 指定临时文件路径，这个路径可以随便写
		if (isOSLinux()) {
			path = "/project/tmp/";
		} else {
			path = "D://tmp/";
		}
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
		return path;
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:46:04 @版本：V1.0 @description：-> 地址ip拼接访问地址
	 */
	public static String getPath_Project(String proName) {
		javax.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/" + proName + "/";

		return basePath;
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:46:20 @版本：V1.0 @description：-> 项目访问地址
	 */
	public static String getPath() {
		javax.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
		return basePath;
	}

	/**
	 * 
	 * @description：-> 得到一个N位随机数
	 * 
	 * @param charCount
	 *            位数
	 * @return
	 *
	 * @作者：xie_ying
	 * @时间：2017年5月4日 下午1:37:50 @版本：V1.0
	 *
	 */
	public static String getCode(int charCount) {
		String charValue = "";
		for (int i = 0; i < charCount; i++) {
			char c = (char) (getRandomInt(0, 10) + '0');
			charValue += String.valueOf(c);
		}
		return charValue;
	}

	/**
	 * 
	 * @description：-> 一个范围内的随机数
	 * 
	 * @param from
	 * @param to
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月25日 上午10:12:51 @版本：V1.0
	 *
	 */
	public static int getRandomInt(int from, int to) {
		Random r = new Random();
		return from + r.nextInt(to - from);
	}

	/**
	 * 
	 * @description：-> Java里面去掉网页里的HTML标记的方法 Java中去掉网页HTML标记的方法 去掉字符串里面的html代码。 要求数据要规范，比如大于小于号要配套,否则会被集体误杀。
	 * 
	 * @param content
	 *            内容
	 * @return 去掉后的内容
	 * 
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月16日 下午5:05:37 @版本：V1.0
	 *
	 */
	public static String stripHtml(Object objContent) {
		try {
			String content = objContent.toString();
			// <p>段落替换为换行
			content = content.replaceAll("<p .*?>", "\r\n");
			// <br><br/>替换为换行
			content = content.replaceAll("<br\\s*/?>", "\r\n");
			// 去掉其它的<>之间的东西
			content = content.replaceAll("\\<.*?>", "");
			// 还原HTML
			// content = HTMLDecoder.decode(content);

			content = content.replaceAll("&nbsp;", "");

			content = content.replaceAll("\r", "");
			content = content.replaceAll("\n", "");
			content = content.replaceAll("\t", "");

			return content.trim();

		} catch (Exception e) {
			// LogClass.log.error("--去掉html-->", e);
			return "";
		}
	}

	/**
	 * 
	 * @description：-> 保留N位小数点
	 * 
	 * @param f
	 * @param format
	 *            格式
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月16日 下午5:35:28 @版本：V1.0
	 *
	 */
	public static double TransNPoint(double f, String format) {
		DecimalFormat df = new DecimalFormat("0." + format);
		return Double.parseDouble(df.format(f));
	}

	/**
	 * 
	 * @description：-> unicode转成中文
	 * 
	 * @param utfString
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月23日 下午4:00:36 @版本：V1.0
	 *
	 */
	public static String convert(String utfString) {
		StringBuilder sb = new StringBuilder();
		int i = -1;
		int pos = 0;

		while ((i = utfString.indexOf("\\u", pos)) != -1) {
			sb.append(utfString.substring(pos, i));
			if (i + 5 < utfString.length()) {
				pos = i + 6;
				sb.append((char) Integer.parseInt(utfString.substring(i + 2, i + 6), 16));
			}
		}

		return sb.toString();
	}

	/**
	 * 
	 * @description：-> 把错误日志获取到String类型，存入日志
	 * 
	 * @param t
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年6月7日 下午4:04:28 @版本：V1.0
	 *
	 */
	public static String printErrorTrace(Throwable e) {
		StringWriter stringWriter = new StringWriter();
		PrintWriter writer = new PrintWriter(stringWriter);
		e.printStackTrace(writer);
		StringBuffer buffer = stringWriter.getBuffer();
		return buffer.toString();
	}

	/**
	 * 
	 * @description：-> 给数据md5加密
	 * 
	 * @param str
	 *            参数
	 * @param frequency
	 *            频率
	 * @param Up
	 *            是否转换成大写
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月4日 下午1:49:20 @版本：V1.0
	 *
	 */
	public static String getMd5(String str, int frequency, boolean Up) {
		if (!StringUtils.isEmpty(str)) {
			try {
				for (int i = 0; i < frequency; i++) {
					str = MD5.md5(str);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}

			if (Up) {
				str = str.toUpperCase();
			}
		}

		return str;
	}

	/**
	 * 
	 * @description：-> 数据返回
	 * 
	 * @param message
	 * @param type
	 *            数据返回格式
	 * @throws Exception
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月15日 上午9:44:42 @版本：V1.0
	 *
	 */
	public static void outPrint(HttpServletResponse response, String message, String type) {
		if (type != "" && type != null && !"".equals(type)) {
			response.setContentType(type + "/html;charset=utf-8");
		} else {
			response.setContentType("text/html;charset=utf-8");
		}
		response.setCharacterEncoding("UTF-8");
		PrintWriter pw = null;
		try {
			pw = response.getWriter();
			pw.write(message);
			pw.flush();
			pw.close();
		} catch (Exception e) {
			LOG.error("----数据返回错误-->" + e);
		}
	}

	/**
	 * 
	 * @description：-> 获取访问IP
	 * 
	 * @param request
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2018年3月14日 上午10:24:40 @版本：V1.0
	 *
	 */
	public static String getIp(javax.servlet.http.HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("x-forwarded-for");
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
		}
		return ip;
	}

	/**
	 * 
	 * @description：-> 身份证验证
	 * 
	 * @param IDNumber
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年8月15日 上午9:42:32、@版本：V1.0
	 */
	public static boolean isIDNumber(String IDNumber) {
		if (IDNumber == null || "".equals(IDNumber)) {
			return false;
		}
		// 定义判别用户身份证号的正则表达式（15位或者18位，最后一位可以为字母）
		String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|"
				+ "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";

		boolean matches = IDNumber.matches(regularExpression);

		// 判断第18位校验值
		if (matches) {

			if (IDNumber.length() == 18) {
				try {
					char[] charArray = IDNumber.toCharArray();
					// 前十七位加权因子
					int[] idCardWi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
					// 这是除以11后，可能产生的11位余数对应的验证码
					String[] idCardY = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
					int sum = 0;
					for (int i = 0; i < idCardWi.length; i++) {
						int current = Integer.parseInt(String.valueOf(charArray[i]));
						int count = current * idCardWi[i];
						sum += count;
					}
					char idCardLast = charArray[17];
					int idCardMod = sum % 11;
					if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
						return true;
					} else {
						System.out.println("身份证最后一位:" + String.valueOf(idCardLast).toUpperCase() + "错误,正确的应该是:" + idCardY[idCardMod].toUpperCase());
						return false;
					}

				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("异常:" + IDNumber);
					return false;
				}
			}

		}
		return matches;
	}

	/**
	 * 
	 * @description：-> 数据base64加密或者解密
	 * 
	 * @param str
	 *            字符串
	 * @param frequency
	 *            加密解密次数
	 * @param type
	 *            类型 0-加密 1-解密
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2017年5月23日 上午10:45:08 @版本：V1.0
	 *
	 */
	public static String base64frequency(String str, int frequency, int type) {
		if (type == 0) {// 加密
			for (int i = 0; i < frequency; i++) {
				str = Base64.getBase64(str);
			}
		} else {// 解密
			for (int i = 0; i < frequency; i++) {
				str = Base64.getFromBase64(str);
			}
		}

		return str;
	}

	/**
	 * 
	 * @description：-> 判断是否是json结构
	 * 
	 * @param value
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年7月9日 下午3:11:47、@版本：V1.0
	 */
	public static boolean isJson(String value) {
		try {
			JSON.parse(value);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 
	 * @description：-> 判断是否是xml结构
	 * 
	 * @param value
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年7月9日 下午3:11:55、@版本：V1.0
	 */
	public static boolean isXML(String value) {
		try {
			DocumentHelper.parseText(value);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 
	 * @description：-> 鉴定是否是数字
	 * 
	 * @param str
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2019年10月28日 下午5:13:08 @版本：V1.0
	 *
	 */
	public static boolean isNumber(String str) {
		try {
			Double.valueOf(str);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/** 获取流中的参数 **/
	public static String getData(HttpServletRequest request) {
		String inputLine = null;
		// 接收到的数据
		StringBuffer recieveData = new StringBuffer();
		BufferedReader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
			while ((inputLine = in.readLine()) != null) {
				recieveData.append(inputLine);
			}
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		} finally {
			try {
				if (null != in) {
					in.close();
				}
			} catch (IOException e) {
				return "";
			}
		}
		return recieveData.toString();
	}

	/** 生成订单号 **/
	public static String getOrderNumber(String type, Long orderId) {
		String number = null;
		switch (type) {
		case PublicConstant.ORDER_TYPE_1:// 主订单订单号
			number = PublicConstant.ORDER_TYPE_1 + "T" + DateUtils.DF_CLOSED.get().format(new Date()) + "N" + PublicMethod.getCode(5);
			break;
		case PublicConstant.ORDER_TYPE_2:// 商品支付订单号生成
			number = PublicConstant.ORDER_TYPE_2 + "T" + DateUtils.DF_CLOSED.get().format(new Date()) + "N" + numberComplementUpZero(orderId.toString(), 8);
			break;
		case PublicConstant.ORDER_TYPE_3:// 退款订单号
			number = PublicConstant.ORDER_TYPE_3 + "R" + DateUtils.DF_CLOSED.get().format(new Date()) + "N" + numberComplementUpZero(orderId.toString(), 8);
			break;
		}
		return number;
	}

	/**
	 * @param totalCount
	 *            总共多少位
	 * @作者：陳曉鬆 @时间：2020年5月5日 上午9:55:31 @版本：V1.0 @description：-> 给一个数字前面补足零
	 */
	public static String numberComplementUpZero(String number, int totalCount) {
		String newString = "";
		for (int i = 0; i < totalCount - number.toString().length(); i++) {
			newString += "0";
		}
		return newString + number.toString();
	}

	/**
	 * 
	 * @description：-> 判断是不是linux系统
	 * 
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2020年1月13日 上午10:37:10 @版本：V1.0
	 *
	 */
	public static boolean isOSLinux() {
		Properties prop = System.getProperties();
		String os = prop.getProperty("os.name");
		if (os != null && os.toLowerCase().indexOf("linux") > -1) {
			return true;
		} else {
			return false;
		}
	}
}
